home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
076-100
/
scopedisk83
/
popcli4
/
popmain.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-19
|
18KB
|
577 lines
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_o_o|\\ Copyright (c) 1986 The Software Distillery. All Rights Reserved */
/* |. o.| || This program may not be distributed without the permission of */
/* | . | || the authors. */
/* | o | || Dave Baker Ed Burnette Stan Chow Jay Denebeim */
/* | . |// Gordon Keener Jack Rouse John Toebes Doug Walker */
/* ====== BBS:(919)-471-6436 VOICE:(919)-469-4210 */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* VERY loosely based on the input.device example by Rob Peck, 12/1/85
*/
#include "popcli.h"
#include "popbug.h"
#include "cback.h"
#ifdef BUGMACROS
#define __BugWindow (*(BPTR *)"BUG") /* 4 bytes, big enuf for a BPTR */
#endif
/************************************************************************/
/* the main program to do the popcli stuff */
/************************************************************************/
#undef global /* Since it really is local in this routine */
void _main()
{
struct cbackstr *cback;
struct MsgPort *port;
int stay = 0;
int shutdown;
short timeout;
struct OURMSG *msg;
register CommandBlock *cb;
int key;
struct Process *us;
#ifdef BUGMACROS
BPTR bugwindow;
#endif
BPTR nullfh;
ULONG sig, portsig, timersig;
struct timerequest *timerreq;
struct MsgPort *timerport;
struct MsgPort *inputDevPort;
struct IOStdReq *inputRequestBlock;
struct Interrupt handlerStuff;
GLOBAL_DATA global;
struct Process *SyncProcess;
int SyncSignal;
char *cmd;
int cmdlen;
struct RexxMsg *amsg;
struct OURMSG pmsg; /* for AREXX message parsing */
int rc;
memset( (char *)&global, 0, sizeof(global) );
DOSBase = (struct DosBase *)OpenLibrary("dos.library",0);
global.blanksignum = -1;
timerreq = NULL;
timerport = NULL;
inputDevPort = NULL;
inputRequestBlock = NULL;
msg = NULL;
timeout = DEFTIME;
/* Fetch our arguments from the wild blue yonder */
us = (struct Process *)FindTask(0);
us->pr_ConsoleTask = NULL;
WaitPort( &(us->pr_MsgPort) );
cback = (struct cbackstr *)GetMsg( &(us->pr_MsgPort) );
global.stdout = cback->stdout;
/* now see if we are already installed */
if ((port = FindPort(PORTNAME)) == NULL)
{
stay = 1; /* remember to hang around when we are done */
#ifdef BUGMACROS
bugwindow = Open(BUGWINDOW,MODE_NEWFILE);
memcpy( "BUG", (char *)&bugwindow, 4 );/* __BugWindow = bugwindow; */
#endif
BUG(("Setting stay to 1 - first time here\n"));
/* not installed, we need to install our own port */
if ((port = MyCreatePort(&global, PORTNAME)) == NULL)
goto abort;
/* Tell everybody we're here... */
popbanner( &global );
}
#ifdef BUGMACROS
else
{
memcpy( "BUG", (char *)&global.stdout, 4 );
}
#endif
/* Bit of a kludge... remove the trailing "\n" so we don't have to */
/* muck with it in popparse(). Put a null on, too; and we can't */
/* overwrite because there may not be enough room. */
cmdlen = cback->cmdlen;
cmd = AllocMem( cmdlen + 1, 0 );
memcpy( cmd, cback->cmd, cmdlen );
if (cmd[cmdlen-1] == '\n')
cmd[cmdlen-1] = '\0';
else
cmd[cmdlen] = '\0';
SyncProcess = cback->SyncProcess;
SyncSignal = cback->SyncSignal;
FreeMem( (char *)cback, cback->msgpart.mn_Length );
/* Save port for handler to use */
global.execport = port;
/* now send the parameter to the waiting program */
if ((msg = (struct OURMSG *)
AllocMem(sizeof(struct OURMSG), MEMF_CLEAR|MEMF_PUBLIC)) == NULL)
goto abort;
/* fill in the message information */
msg->msgpart.mn_Length = sizeof(struct OURMSG);
BUG(("Command to parse: `%s'\n", cmd));
rc = popparse( &global, cmd, msg );
/* We're done with the command line */
FreeMem( cmd, cmdlen+1 );
if (rc == SHUTDOWN)
{
/* Print shutting down message */
poptrailer( &global );
}
/* Get stack size and stuff from our parent, if we're the server */
if (stay)
copyproc( &global, us, SyncProcess );
/* Let the original window go away */
if (global.stdout)
Close(global.stdout);
global.stdout = 0;
/* We got everything, so it's safe to let the parent go away */
if (SyncSignal != -1)
{
Signal((struct Task *)SyncProcess, 1<<SyncSignal);
SyncSignal = -1;
}
global.blankscreen = NULL;
if (stay && msg->interval == 0)
msg->interval = DEFTIME;
BUG(("MSG TO SEND:\n"));
BUG((" Type = %d\n", msg->type));
BUG((" Key = %d\n", msg->key));
BUG((" Interval = %d\n", msg->interval));
BUG((" minmem = %d\n", msg->minmem << 10));
BUG((" minchip = %d\n", msg->minchip << 10));
BUG((" CmdFlags = %02X\n", msg->cmdflags));
BUG((" Command = `%s'\n", msg->command));
PutMsg(port,(struct Message *)msg);
msg = NULL;
/* If we're told to go away */
if ((rc == SHUTDOWN) || (rc == LEAVE) || !stay)
{
goto abort;
}
global.noevents = 0;
/* set the input and output streams to 0 so execute doen't complain */
nullfh = Open("NIL:", MODE_NEWFILE);
if (((inputDevPort = MyCreatePort(&global,NULL)) == NULL) ||
((inputRequestBlock =
CreateIOReq(&global, inputDevPort, sizeof(struct IOStdReq))) == NULL) ||
((timerport = MyCreatePort(&global,NULL)) == NULL) ||
((timerreq = (struct timerequest *)
CreateIOReq(&global,timerport, sizeof(struct timerequest))) == NULL) ||
((global.blanksignum = AllocSignal(-1)) == -1) ||
((GfxBase = (GBasePtr)
OpenLibrary("graphics.library", 0)) == NULL) ||
((IntuitionBase = (IBasePtr)
OpenLibrary("intuition.library", 0)) == NULL) ||
OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)timerreq, 0) ||
OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0))
goto abort;
handlerStuff.is_Data = (APTR)&global;
handlerStuff.is_Code = (VOID(*)())myhandler;
handlerStuff.is_Node.ln_Pri = 51;
timersig = (1 << timerport->mp_SigBit);
portsig = (1 << port->mp_SigBit);
global.unblanksig = 1 << global.blanksignum;
inputRequestBlock->io_Command = IND_ADDHANDLER;
inputRequestBlock->io_Data = (APTR)&handlerStuff;
DoIO((struct IORequest *)inputRequestBlock);
global.buddy = (struct Task *)us;
QueueTimer(&global, timerreq, TIMEINTERVAL);
/* All other fields in newscreen are 0 */
global.newscreen.Width = 320;
global.newscreen.Height = 30;
global.newscreen.Depth = 1;
global.newscreen.BlockPen = 1;
global.newscreen.Type = CUSTOMSCREEN;
shutdown = 0;
while(!shutdown)
{
sig = Wait( portsig | global.unblanksig | timersig );
/* see if we have anything to do */
while ((msg = (struct OURMSG *)GetMsg(port)) != NULL)
{
if ((msg->msgpart.mn_Node.ln_Name) &&
!strcmp(msg->msgpart.mn_Node.ln_Name, "REXX"))
{
/* we've got an ARexx message to parse. */
amsg = (struct RexxMsg *)msg;
BUG(("AREXX!! Command = `%s'\n", amsg->rm_Args[0]));
rc = popparse( &global, amsg->rm_Args[0], &pmsg );
amsg->rm_Result1 = (rc == LEAVE) ? 5 : 0;
amsg->rm_Result2 = 0;
ReplyMsg( (struct Message *)amsg );
/* So our normal msg processing code can handle it */
msg = &pmsg;
}
else
amsg = NULL;
/* See which type of message we have */
switch( msg->type ) {
/*----------------------------------------------------*/
case MSG_ADDKEY:
BUG(("*Add Key %d\n", msg->key));
/* Because of parsing, we stick the interval information */
/* in with the MSG_ADDKEY. There should be a better way */
/* to do this. */
if (msg->interval)
{
timeout = msg->interval;
BUG((" Interval == %d ticks\n", timeout));
}
/* If we already have defined this key, then we can */
/* update its command, else add the key. */
cb = global.keytab[msg->key];
if (!cb)
{
/* Its not there, we need to add the key */
if (cb = (CommandBlock *)
AllocMem(sizeof(CommandBlock),MEMF_PUBLIC))
{
/* Give new key the default command, if message has */
/* no command. */
if (msg->command[0] == '\0')
strcpy(cb->command, DEFCMD);
BUG((" creating <%d> at 0x%08lx\n", msg->key, (long)cb));
}
else
BUG((" !!!! Can't alloc command block!!!\n"));
global.keytab[msg->key] = cb;
}
/* Update the key command, for new or old key */
if (cb)
{
cb->minmem = msg->minmem;
cb->minchip = msg->minchip;
cb->cmdflags = msg->cmdflags;
if (cb && msg->command[0])
{
strcpy(cb->command, msg->command);
}
BUG((" New command = `%s'\n", cb->command));
}
break;
/*----------------------------------------------------*/
case MSG_DELKEY:
BUG(("*Delete Key %d\n", msg->key));
cb = global.keytab[msg->key];
if (cb)
{
BUG((" killing <%d> at 0x%08lx\n", msg->key, (long)cb));
global.keytab[msg->key] = NULL;
FreeMem( (char *)cb, sizeof(CommandBlock) );
}
break;
/*----------------------------------------------------*/
case MSG_EXECUTE:
BUG(("*Execute for key %d\n", msg->key));
cb = global.keytab[msg->key];
if (cb)
{
BUG((" Executing `%s'\n", cb->command));
if (cb->minmem)
{
BUG(("Public memory: REQ: %8d, AVAIL: %8d\n",
cb->minmem << 10,
AvailMem(MEMF_PUBLIC)));
}
if (cb->minchip)
{
BUG(("Chip memory: REQ: %7d, AVAIL: %7d\n",
cb->minchip << 10,
AvailMem(MEMF_CHIP)));
}
if (((cb->minmem == 0) ||
((AvailMem(MEMF_PUBLIC)>>10) >= cb->minmem )) &&
((cb->minchip == 0) ||
((AvailMem(MEMF_CHIP )>>10) >= cb->minchip)))
{
if (!(cb->cmdflags & FLAG_NOWB2F))
WBenchToFront();
if (! Execute(cb->command, nullfh, nullfh))
DisplayBeep(NULL);
}
else
DisplayBeep(NULL);
}
break;
/*----------------------------------------------------*/
case MSG_SHUTDOWN:
BUG(("*Quit: Shut UP!!\n"));
/* Cause us to drop out of loop when we're thru */
shutdown = 1;
break;
/*----------------------------------------------------*/
case MSG_BLANK:
BUG(("*BLANK it out!\n"));
if (global.blankscreen == NULL)
{
if ( (global.blankscreen = OpenScreen(&global.newscreen)) != NULL)
{
BUG(("Screen OFF!!!!!\n"));
SetRGB4(&(global.blankscreen->ViewPort), 0, 0, 0, 0);
OFF_DISPLAY
}
}
break;
/*----------------------------------------------------*/
case MSG_UNBLANK:
BUG(("*UNBLANK it back!\n"));
if (global.blankscreen)
{
CloseScreen(global.blankscreen);
ON_DISPLAY
global.blankscreen = NULL;
global.noevents = 0;
}
break;
/*----------------------------------------------------*/
case MSG_SETTIME:
BUG(("*Timeout set to %d\n", msg->interval));
timeout = msg->interval;
break;
/*----------------------------------------------------*/
default:
BUG(("HEY, I got an unknown message at %08lx!!!!!\n", msg));
}
if (!amsg)
FreeMem((char *)msg, msg->msgpart.mn_Length);
}
if ((sig & global.unblanksig) && global.blankscreen)
{
BUG(("Screen On\n"));
CloseScreen(global.blankscreen);
ON_DISPLAY
global.blankscreen = NULL;
}
if (sig & timersig)
{
/* get rid of the message */
(void)GetMsg(timerport);
QueueTimer(&global, timerreq, TIMEINTERVAL);
if ((global.noevents++ >= timeout) && (global.blankscreen == NULL))
{
if ( (global.blankscreen = OpenScreen(&global.newscreen)) != NULL)
{
BUG(("Screen OFF!!!!!\n"));
SetRGB4(&(global.blankscreen->ViewPort), 0, 0, 0, 0);
OFF_DISPLAY
}
}
}
/* Force our screen to front on a regular basis to handle something */
/* that might put their stuff in front of us while we are supposed to */
/* Be blanking the screen. */
if (global.blankscreen)
{
BUG(("Screen still off\n"));
#if 1
if (((IBasePtr)IntuitionBase)->FirstScreen != global.blankscreen)
ScreenToFront(global.blankscreen);
#endif
OFF_DISPLAY
}
}
BUG(("Normal POPCLI shutdown beginning...\n"));
abort:
if (stay)
BUG(("At `abort'...\n"));
if (msg) FreeMem((char *)msg, msg->msgpart.mn_Length);
if (timerreq != NULL)
{
if (timerreq->tr_node.io_Device != NULL)
{
AbortIO( (struct IORequest *)timerreq );
CloseDevice((struct IORequest *)timerreq);
}
DeleteIOReq(&global, (struct IOStdReq *)timerreq);
}
if (inputRequestBlock != NULL)
{
if (inputRequestBlock->io_Device != NULL)
{
inputRequestBlock->io_Command = IND_REMHANDLER;
inputRequestBlock->io_Data = (APTR)&handlerStuff;
DoIO((struct IORequest *)inputRequestBlock);
CloseDevice((struct IORequest *)inputRequestBlock);
}
DeleteIOReq(&global, inputRequestBlock);
}
if (timerport != NULL) MyDeletePort(&global, timerport);
if (global.blanksignum != -1) FreeSignal(global.blanksignum);
if (global.blankscreen != NULL) CloseScreen(global.blankscreen);
if (IntuitionBase != NULL) CloseLibrary((struct Library *)IntuitionBase);
if (GfxBase != NULL) CloseLibrary((struct Library *)GfxBase);
if (inputDevPort != NULL) MyDeletePort(&global, inputDevPort);
if (stay && (port != NULL))
{
/* Empty the port before we trash it */
while (msg = (struct OURMSG *)GetMsg(port)) /* assign */
FreeMem( (char *)msg, msg->msgpart.mn_Length );
MyDeletePort(&global, port);
BUG(("Port gone...\n"));
}
if (global.stdout)
Close(global.stdout);
if (SyncSignal != -1)
Signal((struct Task *)SyncProcess, 1<<SyncSignal);
if (stay)
{
/* NOTE: "prev" is really used as a "next" here */
for (key = 0; key < 256; key++)
{
if (cb = global.keytab[key])
{
BUG(("Deleting key <%d> at 0x%08lx\n", key, cb));
FreeMem( (char *)cb, sizeof(CommandBlock) );
}
}
}
if (nullfh) Close(nullfh);
#ifdef BUGMACROS
if (stay)
{
int paws = 1000000;
BUG(("..bye bye"));
while(--paws>0);
Close(__BugWindow);
}
#endif
/* Free all our copyproc() stuff, if we were the server */
if (stay)
termproc( &global, (struct Process *)FindTask(NULL) );
if (DOSBase)
CloseLibrary( (struct Library *)DOSBase );
}
#ifdef BUGMACROS
#undef DOSBase
void __stdargs myprintf(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
char *fmt;
long a1, a2, a3, a4, a5, a6, a7, a8, a9;
{
int bytes;
char buff[512];
struct DosLibrary *DOSBase;
if (__BugWindow <= 0) return(0);
bytes = sprintf(buff, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",0);
if (bytes < sizeof(buff))
Write(__BugWindow, buff, bytes);
else
Write(__BugWindow, "!!! msg too big - prepare to die\n",
strlen("!!! msg too big - prepare to die\n"));
CloseLibrary( (struct Library *)DOSBase );
return(0);
}
#endif